package com.runa.monitor.platinterface.meter3_0.session;

import com.alibaba.fastjson.JSON;
import com.runa.monitor.platinterface.meter3_0.handle.AbsMsgHandler;
import com.runa.monitor.platinterface.meter3_0.handle.MeterMsgHandler;
import com.runa.monitor.platinterface.meter3_0.util.MySqlJdbcUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.shade.org.eclipse.util.StringUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.ClientEndpointConfig;
import javax.websocket.ContainerProvider;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @author diandian
 * @Date 2022/11/18 20:43
 */
@Slf4j
@EnableScheduling
@Component
public class WebSocketFactory {

    @Value("${threePointZero.enable:true}")
    private Boolean enable;

    @Value("${threePointZero.url:}")
    private String tpzUrl;

    @Value("${threePointZero.username:}")
    private String tpzUsername;

    @Value("${threePointZero.password:}")
    private String tpzPassword;

    private MySqlJdbcUtil mySqlJdbcUtil;

    private Map<String, AddressInfo> addressInfoMap;

    public WebSocketFactory() {
        this.addressInfoMap = new ConcurrentHashMap<>();
    }

    public SessionProxy createSession(String netEquNo, int type) {
        //一个网络设备号一个session,根据网络设备号，生成会话的唯一编码
        SessionProxy sessionProxy = WebSocketPool.getSession(netEquNo);
        if (sessionProxy != null) {
            Session session = sessionProxy.getSession();
            if (session.isOpen()) {
                return sessionProxy;
            }
        }

        Session session = this.getSession(netEquNo, type);
        if (session == null) {
            return null;
        }
        sessionProxy = new SessionProxy(session, SessionProxy.SessionState.free, netEquNo);

        WebSocketPool.putSession(netEquNo, sessionProxy);
        return sessionProxy;
    }

    private Session getSession(String netEquNo, int type) {
        AbsMsgHandler handler = null;
        switch (type) {
            case 1:
                //计量消息处理
                handler = MeterMsgHandler::new;
                break;
            default:
        }
//        AddressInfo addressInfo = new AddressInfo();
//        addressInfo.setIp("127.0.0.1");
//        addressInfo.setPort(8080);
//        addressInfo.setNetEquNo(netEquNo);
//        addressInfoMap.put(netEquNo, addressInfo);
        AddressInfo info = addressInfoMap.get(netEquNo);
        if (info == null) {
            return null;
        }
        String ip = info.getIp();
        Integer port = info.getPort();
        Session session = this.getSession(netEquNo, ip, port, handler);
        return session;
    }

    private Session getSession(String netEquNo, String ip, int port, AbsMsgHandler handler) {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer(); // 获取WebSocket连接器
        String url = "ws://" + ip + ":" + port;
//        String url = "ws://127.0.0.1:8080/comm/websoc";
        log.info("琅卡博3.0 创建WebSocketContainer");
        Session session = null;
        try {
            ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create();
            ClientEndpointConfig config = builder.build();
            WebSocketClient client = new WebSocketClient(netEquNo, handler);
            session = container.connectToServer(client, config, new URI(url));
            //超时时间为120s
            session.setMaxIdleTimeout(1000 * 60 * 2);
        } catch (Throwable e) {
            
        }
        return session;
    }

    @Scheduled(cron = "0 */5 * * * ?")
    @Async
    public void initNetEquInfoTask() {
        log.info("3.0库数据读取initNetEquInfoTask---enable:" + enable);
        if (!enable) return;
        this.initNetEquInfo();
    }

    public void initNetEquInfo() {
        if (StringUtil.isNotBlank(tpzUrl) && StringUtil.isNotBlank(tpzUsername) && StringUtil.isNotBlank(tpzPassword)) {
            if (mySqlJdbcUtil == null) mySqlJdbcUtil = new MySqlJdbcUtil(tpzUrl, tpzUsername, tpzPassword);
            String sql = "select ne.serialNo,sev.netAddress ,se.port `port` from rcc_e_netEqu ne " +
                    "inner join rcc_E_service se on se.uniqueId = ne.webSocketServiceId " +
                    "inner join rcc_e_server sev on sev.uniqueId = se.serverId ";
            ArrayList<HashMap<String, Object>> query = mySqlJdbcUtil.query(sql);
            log.info("initNetEquInfo执行成功---" + JSON.toJSONString(query));
            for (HashMap<String, Object> map : query) {
                AddressInfo addressInfo = new AddressInfo();
                addressInfo.setIp(String.valueOf(map.get("netAddress")));
                addressInfo.setPort((Integer) map.get("port"));
                String netEquNo = String.valueOf(map.get("serialNo"));
                addressInfo.setNetEquNo(netEquNo);
                addressInfoMap.put(netEquNo, addressInfo);
            }
        }
    }


    @Getter
    @Setter
    static class AddressInfo {
        private String ip;
        private Integer port;
        private String netEquNo;
    }


    public static void main(String[] args) {
        WebSocketFactory factory = new WebSocketFactory("test");
        long convert = TimeUnit.SECONDS.convert(10, TimeUnit.NANOSECONDS);
        for (int i = 0; i < 1000; i++) {
            SessionProxy test = factory.createSession("test", 1);
            /*try {
                test.getSession().getBasicRemote().sendText("testtest");
            } catch (IOException e) {
                
            }*/
            try {
                LockSupport.parkNanos(convert);
            } catch (Exception e) {
                
            }
            System.out.println("test");
        }
    }

    public WebSocketFactory(String test) {
        addressInfoMap = new ConcurrentHashMap<>();
        AddressInfo addressInfo = new AddressInfo();
        addressInfo.setIp("127.0.0.1");
        addressInfo.setPort(9010);
        addressInfo.setNetEquNo(test);
        addressInfoMap.put("test", addressInfo);
    }
}
